#!/usr/bin/env python

# (c) 2007-2011 Helsinki University of Technology and University of Helsinki
# Licensed under the MIT license; see LICENSE.txt for more information.

from ConfigParser import ConfigParser, NoOptionError
from pkg_resources import resource_stream
from rdf import *
import re

DEFAULT_CONFDIR='/etc/harava'
DEFAULT_CONFNAME='harava'

DEFAULT_EXCLUDE_EXTENSIONS = ['.gif','.png','.jpg','.jpeg','.txt','.pdf','.ps',
                              '.doc','.rtf','.ppt','.xls','.css','.js',
                              '.mpg','.wmv','.mov','.bib','.zip','.enl']
DEFAULT_OUTPUT_FORMAT = 'pretty-xml'

class StaticSource:
  def __init__(self, config, name, srctype):
    self._config = config
    self._name = name
    self._type = srctype
  
  def getName(self):
    return self._name
  
  def getType(self):
    return self._type
  
  def getUrls(self):
    return []
  
  def getExcludeUrls(self):
    return []

  def getBlacklist(self):
    return ''
    
  def getDomains(self):
    return []
  
  def getURLRegex(self):
    return ''
  
  def getExcludeExt(self):
    return []
  
  def getWait(self):
    return 0
        
  def getDefaultAudience(self):
    return ''
  
  def getDefaultGenre(self):
    return ''
  
  def getDefaultPublisher(self):
    return ''
  
  def getContentXPath(self):
    return ''
  
  def getHeadlineXPath(self):
    return ''
  
  def getForceEncoding(self):
    return ''
  
  def getForceURLasURI(self):
    return False
  
  def getAdditionalMetadataModels(self):
    return []
  
  def __str__(self):
    return "Source('%s', type='%s')" % (self._name, self._type)
  
  def __hash__(self):
    return hash(self._name) ^ hash(self._type)
  
  

class Source:

  def __init__(self, config, conffile, sectname):
    self._config = config
    self._cf = conffile
    self._sectname = sectname
  
  def getName(self):
    return self._sectname[7:]
  
  def getType(self):
    return self._cf.get(self._sectname, 'type')
  
  def getUrls(self):
    urls = []
    for name,url in self._cf.items(self._sectname):
      if re.match(r'^url\d*$', name):
        urls.append(url)
    return urls
    
  def getExcludeUrls(self):
    excludeurls = []
    for name,url in self._cf.items(self._sectname):
      if name.startswith('excludeurl'):
        excludeurls.append(url)
    return excludeurls
  
  def getBlacklist(self):
    try:
      return self._cf.get(self._sectname, 'blacklist')
    except NoOptionError:
      return None
    
  def getDomains(self):
    domains = []
    for name,url in self._cf.items(self._sectname):
      if name.startswith('domain'):
        domains.append(url)
    return domains
  
  def getURLRegex(self):
    try:
      return self._cf.get(self._sectname, 'urlregex')
    except NoOptionError:
      return None
  
  def getExcludeExt(self):
    try:
      return self._cf.get(self._sectname, 'excludeext').split(',')
    except NoOptionError:
      return DEFAULT_EXCLUDE_EXTENSIONS
  
  def getWait(self):
    try:
      return self._cf.getint(self._sectname, 'wait')
    except NoOptionError:
      return 0

  def getDefaultAudience(self):
    try:
      return self._cf.get(self._sectname, 'defaultAudience')
    except NoOptionError:
      return None
  
  def getDefaultGenre(self):
    try:
      return self._cf.get(self._sectname, 'defaultGenre')
    except NoOptionError:
      return None
  
  def getDefaultPublisher(self):
    try:
      return self._cf.get(self._sectname, 'defaultPublisher')
    except NoOptionError:
      return None
  
  def getContentXPath(self):
    try:
      return self._cf.get(self._sectname, 'contentXPath')
    except NoOptionError:
      return None
  
  def getHeadlineXPath(self):
    try:
      return self._cf.get(self._sectname, 'headlineXPath')
    except NoOptionError:
      return None
  
  def getForceEncoding(self):
    try:
      return self._cf.get(self._sectname, 'forceEncoding')
    except NoOptionError:
      return None

  def getForceURLasURI(self):
    try:
      return self._cf.getboolean(self._sectname, 'forceURLasURI')
    except NoOptionError:
      return False
  
  def getAdditionalMetadataModels(self):
    try:
      models = self._cf.get(self._sectname, 'additionalMetadataModels').strip()
      if models:
        return models.split(',')
      else:
        return []
    except NoOptionError:
      return []
  
  def getOutputFormat(self):
    try:
      return self._cf.get(self._sectname, 'outputformat')
    except NoOptionError:
      return DEFAULT_OUTPUT_FORMAT

  def __str__(self):
    return "Source('%s')" % self.getName()
  
  def __hash__(self):
    return hash(self._sectname)

class Vocabulary:
  def __init__(self, conffile, sectname):
    self._cf = conffile
    self._sectname = sectname

# common attributes

  def getName(self):
    return self._sectname[6:]

  def getURI(self):
    try:
      return self._cf.get(self._sectname, 'uri')
    except NoOptionError:
      return None

  def getType(self):
    return self._cf.get(self._sectname, 'type')
  
  def getLanguage(self):
    return self._cf.get(self._sectname, 'language')
  
  def getAltNames(self):
    try:
      return self._cf.get(self._sectname, 'altnames').decode('UTF-8').split(',')
    except NoOptionError:
      return []

# type "onki"

  def getOnkiName(self):
    return self._cf.get(self._sectname, 'onkiname')
  
  def getTypeRestriction(self):
    try:
      return self._cf.get(self._sectname, 'typerestriction')
    except NoOptionError:
      return None

# type "model"
  
  def getModelName(self):
    return self._cf.get(self._sectname, 'modelname')
  
  def getClasses(self):
    classes = []
    for name,uri in self._cf.items(self._sectname):
      if name.startswith('class'):
        classes.append(uri)
    return classes
    
  def getProperty(self):
    return self._cf.get(self._sectname, 'property')

  def getAltProperty(self):
    try:
      return self._cf.get(self._sectname, 'altproperty')
    except NoOptionError:
      return None

class Config:
  def __init__(self, confdir=DEFAULT_CONFDIR, confname=DEFAULT_CONFNAME):
    self._cf = ConfigParser()
    conffile = "%s/%s.cfg" % (confdir, confname)
    self._cf.read(conffile)
    self._confname = confname

  def getSources(self):
    sourceNames = [sect for sect in self._cf.sections() if sect.startswith('source:')]
    sources = [Source(self, self._cf, sn) for sn in sourceNames]
    return sources
  
  def getVocabularies(self):
    vocabNames = [sect for sect in self._cf.sections() if sect.startswith('vocab:')]
    vocabs = [Vocabulary(self._cf, vn) for vn in vocabNames]
    return vocabs
  
  def getModelSources(self):
    return self._cf.items('model')
  
  def getHTTPProxy(self):
    try:
      return self._cf.get('params', 'http_proxy')
    except NoOptionError:
      return None
  
  def getUserAgent(self):
    return self._cf.get('params', 'useragent')
  
  def getDataDir(self):
    return self._cf.get('params', 'datadir')
  
  def getOutputDir(self):
    return self._cf.get('params', 'outputdir')
  
  def getReportDir(self):
    return self._cf.get('params', 'reportdir')
  
  def getOnkiKey(self):
    return self._cf.get('params', 'onkikey')

  def getBaseURL(self):
    url = self._cf.get('params', 'baseurl')
    if not url: return None
    return url
  
  def getCGIURL(self):
    url = self._cf.get('params', 'cgiurl')
    if not url: return None
    return url
  
  def getConfigName(self):
    return self._confname
